#include <stdio.h>
#include <termios.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>


//设置波特率、奇偶校验位，结束位，数据位
int set_uart(int fd, int speed, int bits, char check, int stop)
{

    struct termios newtio,oldtio;

    // 步骤一：保存原来的串口配置
    if(tcgetattr(fd, &oldtio) != 0)
    {
        //保存失败
        printf("Failed to save the serial port configuration");
        return -1;
    }

    //新结构体清零
    bzero(&newtio, sizeof(newtio));


    // 步骤二：设置控制模式标志
    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;

    // 步骤三：设置数据位
    switch (bits) {
    case 7:
        newtio.c_cflag |= CS7;
        break;
    case 8:
        newtio.c_cflag |= CS8;
        break;
    }

    // 步骤四：设置奇偶校验位
    switch(check) 
    {
        case 'O': // 偶校验位
            newtio.c_cflag |= PARENB;
            newtio.c_cflag |= PARODD;
            newtio.c_iflag |= (INPCK | ISTRIP);
            break;
        case 'E': // 奇校验位
            newtio.c_cflag |= PARENB;
            newtio.c_cflag &= ~PARODD;
            newtio.c_iflag |= (INPCK | ISTRIP);
            break;
        case 'N': // 无校验
            newtio.c_cflag &= ~PARENB;
            break;
    }

    // 步骤五：设置波特率
    switch(speed) 
    {
        case 9600:
            cfsetispeed(&newtio, B9600);
            cfsetospeed(&newtio, B9600);
            break;
        case 115200:
            cfsetispeed(&newtio, B115200);
            cfsetospeed(&newtio, B115200);
            break;
    }


    // 步骤六：设置停止位
    switch(stop) 
    {
        case 1:
            newtio.c_cflag &= ~CSTOPB;  // 1位停止位
            break;
        case 2:
            newtio.c_cflag &= CSTOPB;   // 2位停止位
            break;
    }


    // 步骤七：刷新输入队列
    tcflush(fd, TCIFLUSH);


    // 步骤八：设置配置立刻生效
    if (tcsetattr(fd, TCSANOW, &newtio) != 0) 
    {
        printf("tcsetattr newtio error\n");
        return -2;
    }

    return 0;
}
